{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NLBBAf-QXjNN"
      },
      "source": [
        "#**Protpardelle-1c**\n",
        "\n",
        "Code: [GitHub](https://github.com/ProteinDesignLab/protpardelle-1c/)  \n",
        "Preprint: [bioRxiv](https://www.biorxiv.org/content/10.1101/2025.08.18.670959v2)\n",
        "\n",
        "Note: the Colab is intended for lightweight sampling. For ESMFold self-consistency and production runs, we recommend setting up the environment on a cluster."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "-5X9SUMFKn1K"
      },
      "source": [
        "# Install\n",
        "\n",
        "~5 minutes"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "GUd8oo1b6Fq6"
      },
      "outputs": [],
      "source": [
        "%%bash\n",
        "\n",
        "# Clone the repository\n",
        "git clone https://github.com/ProteinDesignLab/protpardelle-1c.git\n",
        "cd protpardelle-1c\n",
        "\n",
        "# Install environment\n",
        "bash setup.sh\n",
        "uv pip install -qq py3Dmol\n",
        "\n",
        "# Download Protpardelle-1c weights\n",
        "apt-get install aria2 -qq\n",
        "bash download_model_params.sh\n",
        "\n",
        "# Install Foldseek\n",
        "wget https://mmseqs.com/foldseek/foldseek-linux-gpu.tar.gz -qq\n",
        "tar xvfz foldseek-linux-gpu.tar.gz\n",
        "rm foldseek-linux-gpu.tar.gz"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "%env FOLDSEEK_BIN=\"/content/protpardelle-1c/foldseek/bin/foldseek\""
      ],
      "metadata": {
        "id": "0gwJHD-qRUyu"
      },
      "execution_count": null,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "BaAgY5kgKrd-"
      },
      "source": [
        "# Sampling Examples\n",
        "\n",
        "Outputs are saved under `/content/protpardelle-1c/results` by default."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ys_B3Tm7PcF8"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Unconditional sampling\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/00_unconditional.yaml --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6Qv3tLJFPcDy"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Partial diffusion\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/01_partial_diffusion.yaml --motif-dir /content/protpardelle-1c/examples/motifs/nanobody --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "HXFTHYekPcBw"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Motif scaffolding\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/02_motif_scaffolding.yaml --motif-dir /content/protpardelle-1c/examples/motifs/nanobody --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "F08tCNKAPcBL"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# MotifBench benchmark\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/03_motifbench.yaml --motif-dir /content/protpardelle-1c/examples/motifs/motif_bench --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "-NWubECoPb87"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# BindCraft benchmark\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/04_bindcraft.yaml --motif-dir /content/protpardelle-1c/examples/motifs/bindcraft/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0U0sMlgaPb58"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Multichain\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/05_multichain.yaml --motif-dir /content/protpardelle-1c/examples/motifs/nanobody/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EyY6L2_CPb2y"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Thread in a new sequence given a backbone: experimental feature\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/06_fastrelax.yaml --motif-dir /content/protpardelle-1c/examples/motifs/nanobody/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zyE5LL_NPbyu"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Backbone-only La-Proteina / RFdiffusion benchmark\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/07_rfdiffusion.yaml --motif-dir /content/protpardelle-1c/examples/motifs/rfdiffusion/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "grBAcIwVPbtV"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# All-atom La-Proteina / RFdiffusion benchmark\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/08_rfdiffusion_allatom.yaml --motif-dir /content/protpardelle-1c/examples/motifs/rfdiffusion/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uQtu25HMLxuY"
      },
      "outputs": [],
      "source": [
        "%%capture\n",
        "# Generate structure conditioned on sequence: experimental feature, useful as a decoy generator\n",
        "!python -m protpardelle.sample /content/protpardelle-1c/examples/sampling/09_structure_prediction.yaml --motif-dir /content/protpardelle-1c/examples/motifs/nanobody/ --num-samples 8 --num-mpnn-seqs 0"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "kgpjE9SkPuDy"
      },
      "source": [
        "# Visualize\n",
        "\n",
        "Code adapted from Sergey Ovchinnikov's [ESMFold Colab](https://colab.research.google.com/github/sokrypton/ColabFold/blob/main/ESMFold.ipynb)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "h8eDEF_QPvET"
      },
      "outputs": [],
      "source": [
        "# @title {run: \"auto\"}\n",
        "import py3Dmol\n",
        "from string import ascii_uppercase, ascii_lowercase\n",
        "\n",
        "pymol_color_list = [\n",
        "    \"#33ff33\",\n",
        "    \"#00ffff\",\n",
        "    \"#ff33cc\",\n",
        "    \"#ffff00\",\n",
        "    \"#ff9999\",\n",
        "    \"#e5e5e5\",\n",
        "    \"#7f7fff\",\n",
        "    \"#ff7f00\",\n",
        "    \"#7fff7f\",\n",
        "    \"#199999\",\n",
        "    \"#ff007f\",\n",
        "    \"#ffdd5e\",\n",
        "    \"#8c3f99\",\n",
        "    \"#b2b2b2\",\n",
        "    \"#007fff\",\n",
        "    \"#c4b200\",\n",
        "    \"#8cb266\",\n",
        "    \"#00bfbf\",\n",
        "    \"#b27f7f\",\n",
        "    \"#fcd1a5\",\n",
        "    \"#ff7f7f\",\n",
        "    \"#ffbfdd\",\n",
        "    \"#7fffff\",\n",
        "    \"#ffff7f\",\n",
        "    \"#00ff7f\",\n",
        "    \"#337fcc\",\n",
        "    \"#d8337f\",\n",
        "    \"#bfff3f\",\n",
        "    \"#ff7fff\",\n",
        "    \"#d8d8ff\",\n",
        "    \"#3fffbf\",\n",
        "    \"#b78c4c\",\n",
        "    \"#339933\",\n",
        "    \"#66b2b2\",\n",
        "    \"#ba8c84\",\n",
        "    \"#84bf00\",\n",
        "    \"#b24c66\",\n",
        "    \"#7f7f7f\",\n",
        "    \"#3f3fa5\",\n",
        "    \"#a5512b\",\n",
        "]\n",
        "alphabet_list = list(ascii_uppercase + ascii_lowercase)\n",
        "\n",
        "\n",
        "def show_pdb(\n",
        "    pdb_str,\n",
        "    show_sidechains=False,\n",
        "    show_mainchains=False,\n",
        "    color=\"rainbow\",\n",
        "    chains=None,\n",
        "    vmin=50,\n",
        "    vmax=90,\n",
        "    size=(800, 480),\n",
        "    hbondCutoff=4.0,\n",
        "    animate=False,\n",
        "):\n",
        "\n",
        "    view = py3Dmol.view(\n",
        "        js=\"https://3dmol.org/build/3Dmol.js\", width=size[0], height=size[1]\n",
        "    )\n",
        "    if animate:\n",
        "        view.addModelsAsFrames(pdb_str, \"pdb\", {\"hbondCutoff\": hbondCutoff})\n",
        "    else:\n",
        "        view.addModel(pdb_str, \"pdb\", {\"hbondCutoff\": hbondCutoff})\n",
        "    if color == \"pLDDT\":\n",
        "        view.setStyle(\n",
        "            {\n",
        "                \"cartoon\": {\n",
        "                    \"colorscheme\": {\n",
        "                        \"prop\": \"b\",\n",
        "                        \"gradient\": \"roygb\",\n",
        "                        \"min\": vmin,\n",
        "                        \"max\": vmax,\n",
        "                    }\n",
        "                }\n",
        "            }\n",
        "        )\n",
        "    elif color == \"rainbow\":\n",
        "        view.setStyle({\"cartoon\": {\"color\": \"spectrum\"}})\n",
        "    elif color == \"chain\":\n",
        "        for n, chain, color in zip(range(chains), alphabet_list, pymol_color_list):\n",
        "            view.setStyle({\"chain\": chain}, {\"cartoon\": {\"color\": color}})\n",
        "    if show_sidechains:\n",
        "        BB = [\"C\", \"O\", \"N\"]\n",
        "        view.addStyle(\n",
        "            {\n",
        "                \"and\": [\n",
        "                    {\"resn\": [\"GLY\", \"PRO\"], \"invert\": True},\n",
        "                    {\"atom\": BB, \"invert\": True},\n",
        "                ]\n",
        "            },\n",
        "            {\"stick\": {\"colorscheme\": f\"WhiteCarbon\", \"radius\": 0.3}},\n",
        "        )\n",
        "        view.addStyle(\n",
        "            {\"and\": [{\"resn\": \"GLY\"}, {\"atom\": \"CA\"}]},\n",
        "            {\"sphere\": {\"colorscheme\": f\"WhiteCarbon\", \"radius\": 0.3}},\n",
        "        )\n",
        "        view.addStyle(\n",
        "            {\"and\": [{\"resn\": \"PRO\"}, {\"atom\": [\"C\", \"O\"], \"invert\": True}]},\n",
        "            {\"stick\": {\"colorscheme\": f\"WhiteCarbon\", \"radius\": 0.3}},\n",
        "        )\n",
        "    if show_mainchains:\n",
        "        BB = [\"C\", \"O\", \"N\", \"CA\"]\n",
        "        view.addStyle(\n",
        "            {\"atom\": BB}, {\"stick\": {\"colorscheme\": f\"WhiteCarbon\", \"radius\": 0.3}}\n",
        "        )\n",
        "    view.zoomTo()\n",
        "    if animate:\n",
        "        view.animate()\n",
        "    return view\n",
        "\n",
        "\n",
        "pdb_path = \"\"  # @param {type:\"string\"}\n",
        "color = \"rainbow\"  # @param [\"rainbow\", \"chain\"]\n",
        "show_sidechains = True  # @param {type:\"boolean\"}\n",
        "show_mainchains = False  # @param {type:\"boolean\"}\n",
        "\n",
        "\n",
        "pdb_str = []\n",
        "chains = set()\n",
        "with open(pdb_path, \"r\") as fp:\n",
        "    for line in fp.readlines():\n",
        "        if line.startswith((\"ATOM\", \"HETATM\")) and len(line) >= 22:\n",
        "            chain_id = line[21]  # Column 22 in PDB format (0-based index 21)\n",
        "            chains.add(chain_id)\n",
        "            pdb_str.append(line.strip())\n",
        "pdb_str = \"\\n\".join(pdb_str)\n",
        "num_chains = len(chains)\n",
        "\n",
        "\n",
        "show_pdb(\n",
        "    pdb_str,\n",
        "    color=color,\n",
        "    show_sidechains=show_sidechains,\n",
        "    show_mainchains=show_mainchains,\n",
        "    chains=num_chains,\n",
        ").show()"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "collapsed_sections": [
        "-5X9SUMFKn1K"
      ],
      "gpuType": "T4",
      "provenance": []
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}